package playGround.square;

import static org.junit.Assert.*;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import playGround.border.Border;
import playGround.border.Door;
import playGround.border.Wall;
import playGround.dungeon.Direction;

import exceptions.IllegalBorderException;



public class SquareTest {
	
	private Square square;
	private Square square1;
	private Square square2;
	private Square square3;
	private Border wall1;
	private Map<Direction, Border> borders;
	@Before
	public void setUp() throws Exception {
		square = new Square();
		square1 = new Square();
		wall1=new Wall(false);
		Border wall2 = new Wall(false);
		borders = new HashMap<Direction, Border>();
		borders.put(Direction.FLOOR,wall1);
		borders.put(Direction.EAST, wall2);
		square2 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders);
		square3 = new Square(-50,new BigDecimal(10), Scale.CELCIUS, borders);
	}

	@After
	public void tearDown() throws Exception {
	}
	
	 @Test
	public void testColdDamageNull(){
		
		assertEquals(0,square.getColdDamage());
	}
	@Test
	public void addBorderTest(){
		Border wall2 = new Wall(false);
		Map<Direction,Border>borders1 = new HashMap<Direction, Border>();
		borders1.put(Direction.EAST, wall2);
		Square square4 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders1);
		assertEquals(wall2,square4.getBorder(Direction.EAST));
		assertEquals(true,square4.getBorder(Direction.EAST).containsSquare(square4));
	 }
	@Test(expected =IllegalBorderException.class)
	public void addDoorFloorTest(){
		Border door = new Door();
		square2.addBorder(Direction.FLOOR, door);
	}
	@Test
	public void testRemoveBorderByDirection() {
		square2.removeBorder(Direction.EAST);
		assertEquals(square2.getBorder(Direction.EAST),null);
	}
	@Test
	public void testRemoveBorderByBorder() {
		Border wall2 = new Wall(false);
		Map<Direction,Border>borders1 = new HashMap<Direction, Border>();
		borders1.put(Direction.EAST, wall2);
		Square square4 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders1);
		wall2.removeSquare(square4);
		square4.removeBorder(wall2);
		assertEquals(false,square4.hasBorder(wall2));
		
	}
	@Test
	public void testHeatDamage() {
		int dmg = square2.getHeatDamage();
		dmg=0;
		assertNotSame(dmg,square2.getHeatDamage());
	}
	@Test
	public void testColdDamage() {
		int dmg = square3.getColdDamage();
		dmg=0;
		assertNotSame(dmg,square3.getColdDamage());
	}
	@Test
	public void testRustDamage() {
		square1.setHumidity(new BigDecimal(2));
		assertEquals(square2.getRustDamage(),0);
	}
	@Test
	public void testChangeScale(){
		square2.changeScale(Scale.KELVIN);
		assertEquals(573,square2.getTemperature());
	}
	@Test(expected = NullPointerException.class)
	public void testThrowsInConstructor(){
		new Square(6,new BigDecimal(1),null,borders);
	}
	@Test
	public void testThrowsInInhability(){
		square2.setMaxTemperature(Integer.MAX_VALUE);
		square2.setTemperature(Integer.MAX_VALUE);
		assertEquals(square2.getInhability(),Integer.MAX_VALUE);
	}
	@Test(expected = IllegalArgumentException.class)
	public void testThrowsInSetMinTemperature(){
		square2.setMinTemperature(400);
	}
	@Test
	public void testCalculateSlipperyMaterial(){
		Border wall3=new Wall(true);
		Map<Direction,Border> borders1 = new HashMap<Direction, Border>();
		borders1.put(Direction.WEST,wall3);
		Square square4 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders1);
		assertEquals(true,square4.getSlippery());
	}
	@Test
	public void testCalculateSlipperyAboveZero(){
		Border wall3=new Wall(false);
		Map<Direction,Border> borders1 = new HashMap<Direction, Border>();
		borders1.put(Direction.WEST,wall3);
		Square square4 = new Square(300,new BigDecimal(100), Scale.CELCIUS, borders1);
		assertEquals(true,square4.getSlippery());	
	}
	@Test
	public void testCalculateSlipperyUnderZero(){
		Border wall3=new Wall(false);
		Map<Direction,Border> borders1 = new HashMap<Direction, Border>();
		borders1.put(Direction.WEST,wall3);
		Square square4 = new Square(-50,new BigDecimal(20), Scale.CELCIUS, borders1);
		assertEquals(true,square4.getSlippery());
		
	}
	@Test
	public void testControlBorderDoorConflict(){
		Border wall2 = new Wall(false);
		Map<Direction,Border>borders1 = new HashMap<Direction, Border>();
		borders1.put(Direction.EAST, wall2);
		Square square4 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders1);
		Border door = new Door();
		Map<Direction,Border>borders2 = new HashMap<Direction, Border>();
		borders2.put(Direction.WEST, door);
		Square square5 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders2);
		square4.controlBorder(square5, Direction.EAST);
		assertEquals(wall2,square4.getBorder(Direction.EAST));
		assertEquals(wall2,square5.getBorder(Direction.WEST));
	}
	@Test
	public void testControlBorderNoOtherDoorConflict(){
		Border wall2 = new Wall(false);
		Map<Direction,Border>borders1 = new HashMap<Direction, Border>();
		borders1.put(Direction.EAST, wall2);
		Square square4 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders1);
		Border door = new Door();
		Map<Direction,Border>borders2 = new HashMap<Direction, Border>();
		borders2.put(Direction.EAST, door);
		Square square5 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders2);
		square4.controlBorder(square5, Direction.EAST);
		assertEquals(wall2,square4.getBorder(Direction.EAST));
		assertEquals(wall2,square5.getBorder(Direction.WEST));
	}
	@Test
	public void testControlBorderNoThisDoorConflict(){
		Border wall2 = new Wall(false);
		Map<Direction,Border>borders1 = new HashMap<Direction, Border>();
		borders1.put(Direction.NORTH, wall2);
		Square square4 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders1);
		Border door = new Door();
		Map<Direction,Border>borders2 = new HashMap<Direction, Border>();
		borders2.put(Direction.WEST, door);
		Square square5 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders2);
		square4.controlBorder(square5, Direction.EAST);
		assertEquals(wall2,square4.getBorder(Direction.NORTH));
		assertEquals(door,square4.getBorder(Direction.EAST));
		assertEquals(door,square5.getBorder(Direction.WEST));
	}
	@Test
	public void testControlBorderTwoDoorConflict(){
		Border door1 = new Door();
		Map<Direction,Border>borders1 = new HashMap<Direction, Border>();
		borders1.put(Direction.EAST, door1);
		Square square4 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders1);
		Border door = new Door();
		Map<Direction,Border>borders2 = new HashMap<Direction, Border>();
		borders2.put(Direction.WEST, door);
		Square square5 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders2);
		square4.controlBorder(square5, Direction.EAST);
		assertEquals(door1,square4.getBorder(Direction.EAST));
		assertEquals(door1,square5.getBorder(Direction.WEST));
	}
	@Test
	public void testControlBorderTwoWallConflict(){
		Border wall2 = new Wall(false);
		Map<Direction,Border>borders1 = new HashMap<Direction, Border>();
		borders1.put(Direction.EAST, wall2);
		Square square4 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders1);
		Border door = new Wall(true);
		Map<Direction,Border>borders2 = new HashMap<Direction, Border>();
		borders2.put(Direction.WEST, door);
		Square square5 = new Square(300,new BigDecimal(10), Scale.CELCIUS, borders2);
		square4.controlBorder(square5, Direction.EAST);
		assertEquals(wall2,square4.getBorder(Direction.EAST));
		assertEquals(wall2,square5.getBorder(Direction.WEST));
	}
	@Test
	public void testTerminate(){
		Border testWall1=new Wall(false);
		square.addBorder(Direction.CEILING, testWall1);
		square.terminate();
		assertFalse(testWall1.containsSquare(square));
	}
	
	@Test(expected = IllegalBorderException.class)
	public void testBorderRemoveWallTest(){
		square2.removeBorder(wall1);
	}
		
}
